From d90f68966f55cc5666d7f7ffd1dd2c84d1553819 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 14 Mar 2006 16:00:16 +0100 Subject: [PATCH] When both stolen and blocked are rounded down, it is possible for the final increment of the cpu local processed_system_time to move the cpu local system time ahead a bit further than expected - but still proper wrt. wall clock time. This gives problems on a next timer interrupt, when stolen and blocked both get rounded up and end up incrementing the per cpu processed_system_time too far. These simple checks make sure that the cpu local processed_system_time never gets advanced too far. Not advancing the variable now should be fine, since we'll increment it at the next timer tick... This patch has made the "time went backwards" error messages go away completely. Signed-off-by: Rik van Riel Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c index ee5bbe160f..62139abbe4 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c @@ -645,7 +645,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) unlikely(delta_cpu < -(s64)permitted_clock_jitter)) && printk_ratelimit()) { printk("Timer ISR/%d: Time went backwards: " - "delta=%lld cpu_delta=%lld shadow=%lld " + "delta=%lld delta_cpu=%lld shadow=%lld " "off=%lld processed=%lld cpu_processed=%lld\n", cpu, delta, delta_cpu, shadow->system_timestamp, (s64)get_nsec_offset(shadow), @@ -675,8 +675,10 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) * HACK: Passing NULL to account_steal_time() * ensures that the ticks are accounted as stolen. */ - if (stolen > 0) { + if ((stolen > 0) && (delta_cpu > 0)) { delta_cpu -= stolen; + if (unlikely(delta_cpu < 0)) + stolen += delta_cpu; /* clamp local-time progress */ do_div(stolen, NS_PER_TICK); per_cpu(processed_stolen_time, cpu) += stolen * NS_PER_TICK; per_cpu(processed_system_time, cpu) += stolen * NS_PER_TICK; @@ -688,8 +690,10 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) * HACK: Passing idle_task to account_steal_time() * ensures that the ticks are accounted as idle/wait. */ - if (blocked > 0) { + if ((blocked > 0) && (delta_cpu > 0)) { delta_cpu -= blocked; + if (unlikely(delta_cpu < 0)) + blocked += delta_cpu; /* clamp local-time progress */ do_div(blocked, NS_PER_TICK); per_cpu(processed_blocked_time, cpu) += blocked * NS_PER_TICK; per_cpu(processed_system_time, cpu) += blocked * NS_PER_TICK; -- 2.30.2